Function Basics
I. Functions
Resources:
function favoriteAnimal(animal) {
return animal + " is my favorite animal!"
}
console.log(favoriteAnimal('Goat'));
- The function definition is written on the first line
function favoriteAnimal()
. - Parameters are the items listed between the parentheses
()
in the function declaration. Function arguments are the actual values we decide to pass to the function. →animal
is the parameter in this case.- Sometimes, parameters are optional and you don’t have to specify them. Rest Parameter Syntax (
...param1
) allows the function to accept any number of arguments and gathers them into an array namedparam1
. - You can assign the parameter to a default value → default parameters, a value that will be used when you don’t pass any argument to the function.
function hello (name = "Someone"){
console.log(`Hello ${name}!`);
}
hello("Ari"); // Hello Ari!
hello(); // Hello Someone! - Sometimes, parameters are optional and you don’t have to specify them. Rest Parameter Syntax (
- The
return
value is the value a function returns when it completes. In this case, the function returns a string, specifically,Goat is my favorite animal!
- Some functions don’t return any value, they’re called
void
functions. - A function with an empty
return
returnsundefined
.
- Some functions don’t return any value, they’re called
- We call our function at the last line
favoriteAnimal('Goat')
, we’re passing the value'Goat'
inside the function.
1. Built-in Browser Functions
JavaScript has many built-in functions to allow you to do useful things without having to write all that code yourself.
const myNumber = Math.random();
// the random() function generates a random number
const myText = "I am a string";
const newString = myText.replace("string", "a bunch of words");
// manipulate a string with the replace() function
2. Anonymous Functions
// normal function
function myFunction(){
console.log("Hello!");
}
// a function without a name
// anonymous function
(function (){
console.log("Hello!");
})
You’ll often use an anonymous function when another function expects to receive another function as a parameter. The function parameter is often passed as an anonymous function. → callback function
3. Callback Functions
A callback function is a function passed as an argument to another function, with the intention of being executed later. It allows one function to call another function at a specific time or after a certain task is completed.
// declare the greet() function
function greet(name, display){
const message = "Hello" + name;
// invoke callback function
display(message);
}
// declare the callback function
function displayMessage(message){
console.log(message);
}
// call the greet() function
// here you're passing the reference to displayMessage callback function
// not calling the displayMessage() function directly
greet("Alice", displayMessage);
4. [[02. Factory Functions and the Module Pattern#I. Scopes|Function Scope]]
When you create a function, the variables and other things defined inside the function exist only within the scope of that function, unreachable by the code outside the functions.
The top-level outside all functions is called the global scope, values defined in the global scope is accessible everywhere in the code.
const name = "Chris"; // global variable
function greeting() {
const company = "Google"; //local variable
console.log(`Hello ${name}: welcome to ${company}.`);
}
greeting();
console.log(company);
// nothing because the local variable company exists only within the scope of the greeting() function
5. Function Expression vs Function Declaration
1. Function Declaration
A function declaration is a function, declared as a separate statement, in the main code flow.
function sum(a, b){
return a + b;
}
- A function declaration can be called earlier than it is defined because a global function declaration is created when JavaScript is preparing to start the script (hosting)→ it is visible in the whole script, no matter where it is.
// called before declaration
// the function can still be called even though it hasn't been declared
// this is thanks to hoisting
sayHi("John"); // Hello, John
// function declaration
function sayHi(name){
console.log(`Hello, ${name}`);
}
2. Function Expression
A function expression is a function, created inside an expression or another syntax construct.
// assigns the return value of the function to variable sum
let sum = function(a, b){
return a + b;
};
- Function expressions are created when the execution reaches them.
// called before the expression
sayHi("John"); // error!
// function declaration
let sayHi = function (name){
console.log(`Hello, ${name}`);
}
A use for function expression: Most of the time it’s preferred to use function declaration over function expression because of the flexibility. However, there are certain situations where using a function expression is better.
Example:
let age = prompt("What is your age?");
if(age < 18){
// declare function
function welcome(){
console.log("Hello!");
} else {
// declare function
function welcome(){
console.log("Greeting!");
}
}
}
welcome(); // error, function welcome is out of scope here → undefined
To make the welcome()
function accessible from outside the if
block, we can use function expression:
let age = prompt("What is your age?");
let welcome; // declare this variable globally
if (age < 18){
// function expression
welcome = function(){
console.log("Hello!");
}
} else{
// function expression
welcome = function(){
console.log("Greeting!");
}
}
welcome(); // Hello!
6. Arrow Function*
A simple and concise syntax for creating a function that’s often better than function expressions is called arrow functions.
// syntax, multiline arrow function
let sum = (a, b, c) => {
let result = a + b + c;
return result;
}
// it can become simpler, with no brackets, only one line
let sum = (a, b) => a + b;
// This arrow function is a shorter form of:
let sum = function(a, b) {
return a + b;
};
// if there's only one argument, the parentheses can be omitted
let double = n => n * 2;
// Example:
// normal function
function myFunction(){
console.log("Hello!");
}
// arrow function
let myFunction = () => {
console.log("Hello!");
}
The function part 5 can now be rewritten using arrow function and conditional operator:
let age = prompt("What is your age?");
let welcome = (age < 18) ? () => console.log("Hello!") :
() => console.log("Greetings!");
welcome();
Note: Code readability is much more important than writing short code.
II. JavaScript Call Stack
Resources:
A call stack is a way for the JavaScript engine to manage the execution of function calls in a program. It has information on what function is currently being run and what functions are invoked from within that function.
The JavaScript engine uses the call stack to also manage execution contexts:
- The global execution context.
- Function execution context.
1. How it Works
Because it’s a stack, it works based on the principle: last-in-first-out (LIFO).
- When you execute a script, the JavaScript engine creates a global execution context and pushes it on top of the call stack.
- Whenever a function is called, the JavaScript engine creates a new function execution context, pushes it on top of the call stack, and starts executing the function.
- If a function calls another function, the JavaScript engine creates a new function execution context for the function being called and pushes it on top of the call stack.
- When the current function completes, the JavaScript engine pops it off the call stack and resumes the execution where it left off.
- The script will stop when the call stack is empty.**
function add (a, b){
return a + b;
}
function average(a, b){
let sum = add (a, b);
return sum / 2;
}
let x = average (10, 20);
Call Stack Visualization | |
---|---|
1. When the JavaScript engine executes the script above, it places the global execution context main() or global() on the call stack | 2. The JavaScript engine executes the call to average(10, 20) and creates a function execution context for average() , pushing it on top of the call stack. |
3. The average() function calls add() function → the JavaScript engine creates another function execution context for add() , places it on top of the call stack. | 4. The JavaScript engine finishes executing the add() function and pops it off the call stack. |
5. The average() function is on top of the call stack, the JavaScript engine completes executing it and pops it off the call stack. | 6. The call stack stops executing when the call stack is empty. |
2. Stack Overflow
The call stack has a fixed size, depending on the implementation of the host environment, either the web browser or Node.js. If the number of execution contexts exceeds the size of the stack, a stack overflow error will occur.
// example:
// a recursive function that has no exit condition
// this will cause a stack overflow error
function fn(){
// calls itself, recursive
fn();
}
fn(); // stack overflow
3. Asynchronous JavaScript
JavaScript is a single-threaded programming language, unlike Java, or C++, etc. → The JavaScript engine has only one call stack.
- When executing a script, the JavaScript engine executes code from top to bottom, line by line → synchronous.
- To be more efficient, the JavaScript engine can execute other tasks while waiting for another task to be completed → asynchronous. To do this, the JavaScript engine uses an event loop